home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_061 / microemacs / word.c < prev   
C/C++ Source or Header  |  1992-05-06  |  16KB  |  538 lines

  1. /*
  2.  * The routines in this file implement commands that work word or a
  3.  * paragraph at a time.  There are all sorts of word mode commands.  If I
  4.  * do any sentence mode commands, they are likely to be put in this file. 
  5.  */
  6.  
  7. #if    MEGAMAX & ST520
  8. overlay    "word"
  9. #endif
  10.  
  11. #include        <stdio.h>
  12. #include        "estruct.h"
  13. #include    "edef.h"
  14.  
  15. /* Word wrap on n-spaces. Back-over whatever precedes the point on the current
  16.  * line and stop on the first word-break or the beginning of the line. If we
  17.  * reach the beginning of the line, jump back to the end of the word and start
  18.  * a new line.  Otherwise, break the line at the word-break, eat it, and jump
  19.  * back to the end of the word.
  20.  * Returns TRUE on success, FALSE on errors.
  21.  */
  22. wrapword(f, n)
  23.  
  24. int f;        /* default flag */
  25. int n;        /* numeric argument */
  26.  
  27. {
  28.         register int cnt;    /* size of word wrapped to next line */
  29.     register int c;        /* charector temporary */
  30.  
  31.     /* backup from the <NL> 1 char */
  32.         if (!backchar(0, 1))
  33.             return(FALSE);
  34.  
  35.     /* back up until we aren't in a word,
  36.        make sure there is a break in the line */
  37.         cnt = 0;
  38.     while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
  39.                 && (c != '\t')) {
  40.                 cnt++;
  41.                 if (!backchar(0, 1))
  42.                         return(FALSE);
  43.         /* if we make it to the beginning, start a new line */
  44.         if (curwp->w_doto == 0) {
  45.             gotoeol(FALSE, 0);
  46.             return(lnewline());
  47.         }
  48.         }
  49.  
  50.     /* delete the forward white space */
  51.         if (!forwdel(0, 1))
  52.                 return(FALSE);
  53.  
  54.     /* put in a end of line */
  55.         if (!lnewline())
  56.                 return(FALSE);
  57.  
  58.     /* and past the first word */
  59.     while (cnt-- > 0) {
  60.         if (forwchar(FALSE, 1) == FALSE)
  61.             return(FALSE);
  62.     }
  63.         return(TRUE);
  64. }
  65.  
  66. /*
  67.  * Move the cursor backward by "n" words. All of the details of motion are
  68.  * performed by the "backchar" and "forwchar" routines. Error if you try to
  69.  * move beyond the buffers.
  70.  */
  71. backword(f, n)
  72. {
  73.         if (n < 0)
  74.                 return (forwword(f, -n));
  75.         if (backchar(FALSE, 1) == FALSE)
  76.                 return (FALSE);
  77.         while (n--) {
  78.                 while (inword() == FALSE) {
  79.                         if (backchar(FALSE, 1) == FALSE)
  80.                                 return (FALSE);
  81.                 }
  82.                 while (inword() != FALSE) {
  83.                         if (backchar(FALSE, 1) == FALSE)
  84.                                 return (FALSE);
  85.                 }
  86.         }
  87.         return (forwchar(FALSE, 1));
  88. }
  89.  
  90. /*
  91.  * Move the cursor forward by the specified number of words. All of the motion
  92.  * is done by "forwchar". Error if you try and move beyond the buffer's end.
  93.  */
  94. forwword(f, n)
  95. {
  96.         if (n < 0)
  97.                 return (backword(f, -n));
  98.         while (n--) {
  99. #if    NFWORD
  100.                 while (inword() != FALSE) {
  101.                         if (forwchar(FALSE, 1) == FALSE)
  102.                                 return (FALSE);
  103.                 }
  104. #endif
  105.                 while (inword() == FALSE) {
  106.                         if (forwchar(FALSE, 1) == FALSE)
  107.                                 return (FALSE);
  108.                 }
  109. #if    NFWORD == 0
  110.                 while (inword() != FALSE) {
  111.                         if (forwchar(FALSE, 1) == FALSE)
  112.                                 return (FALSE);
  113.                 }
  114. #endif
  115.         }
  116.     return(TRUE);
  117. }
  118.  
  119. /*
  120.  * Move the cursor forward by the specified number of words. As you move,
  121.  * convert any characters to upper case. Error if you try and move beyond the
  122.  * end of the buffer. Bound to "M-U".
  123.  */
  124. upperword(f, n)
  125. {
  126.         register int    c;
  127.  
  128.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  129.         return(rdonly());    /* we are in read only mode    */
  130.         if (n < 0)
  131.                 return (FALSE);
  132.         while (n--) {
  133.                 while (inword() == FALSE) {
  134.                         if (forwchar(FALSE, 1) == FALSE)
  135.                                 return (FALSE);
  136.                 }
  137.                 while (inword() != FALSE) {
  138.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  139.                         if (c>='a' && c<='z') {
  140.                                 c -= 'a'-'A';
  141.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  142.                                 lchange(WFHARD);
  143.                         }
  144.                         if (forwchar(FALSE, 1) == FALSE)
  145.                                 return (FALSE);
  146.                 }
  147.         }
  148.         return (TRUE);
  149. }
  150.  
  151. /*
  152.  * Move the cursor forward by the specified number of words. As you move
  153.  * convert characters to lower case. Error if you try and move over the end of
  154.  * the buffer. Bound to "M-L".
  155.  */
  156. lowerword(f, n)
  157. {
  158.         register int    c;
  159.  
  160.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  161.         return(rdonly());    /* we are in read only mode    */
  162.         if (n < 0)
  163.                 return (FALSE);
  164.         while (n--) {
  165.                 while (inword() == FALSE) {
  166.                         if (forwchar(FALSE, 1) == FALSE)
  167.                                 return (FALSE);
  168.                 }
  169.                 while (inword() != FALSE) {
  170.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  171.                         if (c>='A' && c<='Z') {
  172.                                 c += 'a'-'A';
  173.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  174.                                 lchange(WFHARD);
  175.                         }
  176.                         if (forwchar(FALSE, 1) == FALSE)
  177.                                 return (FALSE);
  178.                 }
  179.         }
  180.         return (TRUE);
  181. }
  182.  
  183. /*
  184.  * Move the cursor forward by the specified number of words. As you move
  185.  * convert the first character of the word to upper case, and subsequent
  186.  * characters to lower case. Error if you try and move past the end of the
  187.  * buffer. Bound to "M-C".
  188.  */
  189. capword(f, n)
  190. {
  191.         register int    c;
  192.  
  193.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  194.         return(rdonly());    /* we are in read only mode    */
  195.         if (n < 0)
  196.                 return (FALSE);
  197.         while (n--) {
  198.                 while (inword() == FALSE) {
  199.                         if (forwchar(FALSE, 1) == FALSE)
  200.                                 return (FALSE);
  201.                 }
  202.                 if (inword() != FALSE) {
  203.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  204.                         if (c>='a' && c<='z') {
  205.                                 c -= 'a'-'A';
  206.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  207.                                 lchange(WFHARD);
  208.                         }
  209.                         if (forwchar(FALSE, 1) == FALSE)
  210.                                 return (FALSE);
  211.                         while (inword() != FALSE) {
  212.                                 c = lgetc(curwp->w_dotp, curwp->w_doto);
  213.                                 if (c>='A' && c<='Z') {
  214.                                         c += 'a'-'A';
  215.                                         lputc(curwp->w_dotp, curwp->w_doto, c);
  216.                                         lchange(WFHARD);
  217.                                 }
  218.                                 if (forwchar(FALSE, 1) == FALSE)
  219.                                         return (FALSE);
  220.                         }
  221.                 }
  222.         }
  223.         return (TRUE);
  224. }
  225.  
  226. /*
  227.  * Kill forward by "n" words. Remember the location of dot. Move forward by
  228.  * the right number of words. Put dot back where it was and issue the kill
  229.  * command for the right number of characters. Bound to "M-D".
  230.  */
  231. delfword(f, n)
  232. {
  233.         register LINE   *dotp;
  234.         register int    doto;
  235.         long size;
  236.  
  237.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  238.         return(rdonly());    /* we are in read only mode    */
  239.         if (n < 0)
  240.                 return (FALSE);
  241.         if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
  242.                 kdelete();              /* last wasn't a kill.  */
  243.         thisflag |= CFKILL;
  244.         dotp = curwp->w_dotp;
  245.         doto = curwp->w_doto;
  246.         size = 0;
  247.         while (n--) {
  248. #if    NFWORD
  249.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  250.             if (forwchar(FALSE,1) == FALSE)
  251.                 return(FALSE);
  252.             ++size;
  253.         }
  254.  
  255.         while (inword() != FALSE) {
  256.             if (forwchar(FALSE,1) == FALSE)
  257.                 return(FALSE);
  258.             ++size;
  259.         }
  260.  
  261.                 while ((inword() == FALSE) &&
  262.                 (curwp->w_doto != llength(curwp->w_dotp))) {
  263.                         if (forwchar(FALSE, 1) == FALSE)
  264.                                 return (FALSE);
  265.                         ++size;
  266.                 }
  267. #else
  268.                 while (inword() == FALSE) {
  269.                         if (forwchar(FALSE, 1) == FALSE)
  270.                                 return (FALSE);
  271.                         ++size;
  272.                 }
  273.  
  274.                 while (inword() != FALSE) {
  275.                         if (forwchar(FALSE, 1) == FALSE)
  276.                                 return (FALSE);
  277.                         ++size;
  278.                 }
  279. #endif
  280.         }
  281.         curwp->w_dotp = dotp;
  282.         curwp->w_doto = doto;
  283.         return (ldelete(size, TRUE));
  284. }
  285.  
  286. /*
  287.  * Kill backwards by "n" words. Move backwards by the desired number of words,
  288.  * counting the characters. When dot is finally moved to its resting place,
  289.  * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
  290.  */
  291. delbword(f, n)
  292. {
  293.         long size;
  294.  
  295.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  296.         return(rdonly());    /* we are in read only mode    */
  297.         if (n < 0)
  298.                 return (FALSE);
  299.         if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
  300.                 kdelete();              /* last wasn't a kill.  */
  301.         thisflag |= CFKILL;
  302.         if (backchar(FALSE, 1) == FALSE)
  303.                 return (FALSE);
  304.         size = 0;
  305.         while (n--) {
  306.                 while (inword() == FALSE) {
  307.                         if (backchar(FALSE, 1) == FALSE)
  308.                                 return (FALSE);
  309.                         ++size;
  310.                 }
  311.                 while (inword() != FALSE) {
  312.                         if (backchar(FALSE, 1) == FALSE)
  313.                                 return (FALSE);
  314.                         ++size;
  315.                 }
  316.         }
  317.         if (forwchar(FALSE, 1) == FALSE)
  318.                 return (FALSE);
  319.         return (ldelete(size, TRUE));
  320. }
  321.  
  322. /*
  323.  * Return TRUE if the character at dot is a character that is considered to be
  324.  * part of a word. The word character list is hard coded. Should be setable.
  325.  */
  326. inword()
  327. {
  328.         register int    c;
  329.  
  330.         if (curwp->w_doto == llength(curwp->w_dotp))
  331.                 return (FALSE);
  332.         c = lgetc(curwp->w_dotp, curwp->w_doto);
  333.         if (c>='a' && c<='z')
  334.                 return (TRUE);
  335.         if (c>='A' && c<='Z')
  336.                 return (TRUE);
  337.         if (c>='0' && c<='9')
  338.                 return (TRUE);
  339.         if (c=='$' || c=='_')                   /* For identifiers      */
  340.                 return (TRUE);
  341.         return (FALSE);
  342. }
  343.  
  344. #if    WORDPRO
  345. fillpara(f, n)    /* Fill the current paragraph according to the current
  346.            fill column                        */
  347.  
  348. int f, n;    /* deFault flag and Numeric argument */
  349.  
  350. {
  351.     register int c;            /* current char durring scan    */
  352.     register int wordlen;        /* length of current word    */
  353.     register int clength;        /* position on line during fill    */
  354.     register int i;            /* index during word copy    */
  355.     register int newlength;        /* tentative new line length    */
  356.     register int eopflag;        /* Are we at the End-Of-Paragraph? */
  357.     register int firstflag;        /* first word? (needs no space)    */
  358.     register LINE *eopline;        /* pointer to line just past EOP */
  359.     register int dotflag;        /* was the last char a period?    */
  360.     char wbuf[NSTRING];        /* buffer for current word    */
  361.  
  362.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  363.         return(rdonly());    /* we are in read only mode    */
  364.     if (fillcol == 0) {    /* no fill column set */
  365.         mlwrite("No fill column set");
  366.         return(FALSE);
  367.     }
  368.  
  369.     /* record the pointer to the line just past the EOP */
  370.     gotoeop(FALSE, 1);
  371.     eopline = lforw(curwp->w_dotp);
  372.  
  373.     /* and back top the beginning of the paragraph */
  374.     gotobop(FALSE, 1);
  375.  
  376.     /* initialize various info */
  377.     clength = curwp->w_doto;
  378.     if (clength && curwp->w_dotp->l_text[0] == TAB)
  379.         clength = 8;
  380.     wordlen = 0;
  381.     dotflag = FALSE;
  382.  
  383.     /* scan through lines, filling words */
  384.     firstflag = TRUE;
  385.     eopflag = FALSE;
  386.     while (!eopflag) {
  387.         /* get the next character in the paragraph */
  388.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  389.             c = ' ';
  390.             if (lforw(curwp->w_dotp) == eopline)
  391.                 eopflag = TRUE;
  392.         } else
  393.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  394.  
  395.         /* and then delete it */
  396.         ldelete(1L, FALSE);
  397.  
  398.         /* if not a separator, just add it in */
  399.         if (c != ' ' && c != '\t') {
  400.             dotflag = (c == '.');        /* was it a dot */
  401.             if (wordlen < NSTRING - 1)
  402.                 wbuf[wordlen++] = c;
  403.         } else if (wordlen) {
  404.             /* at a word break with a word waiting */
  405.             /* calculate tantitive new length with word added */
  406.             newlength = clength + 1 + wordlen;
  407.             if (newlength <= fillcol) {
  408.                 /* add word to current line */
  409.                 if (!firstflag) {
  410.                     linsert(1, ' '); /* the space */
  411.                     ++clength;
  412.                 }
  413.                 firstflag = FALSE;
  414.             } else {
  415.                 /* start a new line */
  416.                 lnewline();
  417.                 clength = 0;
  418.             }
  419.  
  420.             /* and add the word in in either case */
  421.             for (i=0; i<wordlen; i++) {
  422.                 linsert(1, wbuf[i]);
  423.                 ++clength;
  424.             }
  425.             if (dotflag) {
  426.                 linsert(1, ' ');
  427.                 ++clength;
  428.             }
  429.             wordlen = 0;
  430.         }
  431.     }
  432.     /* and add a last newline for the end of our new paragraph */
  433.     lnewline();
  434.     return(TRUE);
  435. }
  436.  
  437. killpara(f, n)    /* delete n paragraphs starting with the current one */
  438.  
  439. int f;    /* default flag */
  440. int n;    /* # of paras to delete */
  441.  
  442. {
  443.     register int status;    /* returned status of functions */
  444.  
  445.     while (n--) {        /* for each paragraph to delete */
  446.  
  447.         /* mark out the end and beginning of the para to delete */
  448.         gotoeop(FALSE, 1);
  449.  
  450.         /* set the mark here */
  451.             curwp->w_markp = curwp->w_dotp;
  452.             curwp->w_marko = curwp->w_doto;
  453.  
  454.         /* go to the beginning of the paragraph */
  455.         gotobop(FALSE, 1);
  456.         curwp->w_doto = 0;    /* force us to the beginning of line */
  457.     
  458.         /* and delete it */
  459.         if ((status = killregion(FALSE, 1)) != TRUE)
  460.             return(status);
  461.  
  462.         /* and clean up the 2 extra lines */
  463.         ldelete(2L, TRUE);
  464.     }
  465.     return(TRUE);
  466. }
  467.  
  468.  
  469. /*    wordcount:    count the # of words in the marked region,
  470.             along with average word sizes, # of chars, etc,
  471.             and report on them.            */
  472.  
  473. wordcount(f, n)
  474.  
  475. int f, n;    /* ignored numeric arguments */
  476.  
  477. {
  478.     register LINE *lp;    /* current line to scan */
  479.     register int offset;    /* current char to scan */
  480.     long size;        /* size of region left to count */
  481.     register int ch;    /* current character to scan */
  482.     register int wordflag;    /* are we in a word now? */
  483.     register int lastword;    /* were we just in a word? */
  484.     long nwords;        /* total # of words */
  485.     long nchars;        /* total number of chars */
  486.     int nlines;        /* total number of lines in region */
  487.     int avgch;        /* average number of chars/word */
  488.     int status;        /* status return code */
  489.     REGION region;        /* region to look at */
  490.  
  491.     /* make sure we have a region to count */
  492.         if ((status = getregion(®ion)) != TRUE)
  493.                 return(status);
  494.     lp = region.r_linep;
  495.     offset = region.r_offset;
  496.     size = region.r_size;
  497.  
  498.     /* count up things */
  499.     lastword = FALSE;
  500.     nchars = 0L;
  501.     nwords = 0L;
  502.     nlines = 0;
  503.     while (size--) {
  504.  
  505.         /* get the current character */
  506.         if (offset == llength(lp)) {    /* end of line */
  507.             ch = '\n';
  508.             lp = lforw(lp);
  509.             offset = 0;
  510.             ++nlines;
  511.         } else {
  512.             ch = lgetc(lp, offset);
  513.             ++offset;
  514.         }
  515.  
  516.         /* and tabulate it */
  517.         wordflag = ((ch >= 'a' && ch <= 'z') ||
  518.                 (ch >= 'A' && ch <= 'Z') ||
  519.                 (ch >= '0' && ch <= '9') ||
  520.                 (ch == '$' || ch == '_'));
  521.         if (wordflag == TRUE && lastword == FALSE)
  522.             ++nwords;
  523.         lastword = wordflag;
  524.         ++nchars;
  525.     }
  526.  
  527.     /* and report on the info */
  528.     if (nwords > 0L)
  529.         avgch = (int)((100L * nchars) / nwords);
  530.     else
  531.         avgch = 0;
  532.  
  533.     mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
  534.         nwords, nchars, nlines + 1, avgch);
  535.     return(TRUE);
  536. }
  537. #endif
  538.